﻿using Ini.Net;
using Stepon.FaceRecognization;
using Stepon.FaceRecognization.Common;
using Stepon.FaceRecognization.Detection;
using Stepon.FaceRecognization.Recognization;
using Stepon.FaceRecognization.Tracking;
using System;
using System.Drawing;

namespace IdCardFaceIdentifier
{
    public class ArcFaceApi
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(ArcFaceApi));
        private const string Sn = "libs\\SN.ini";

        private readonly FaceTracking _traking;
        private readonly FaceRecognize _recognize;
        private readonly FaceProcessor _processor;
        private readonly FaceDetection _detection;

        private FaceModel faceModel;

        public ArcFaceApi()
        {
            try
            {
                var iniFile = new IniFile(Sn);

                var appId = iniFile.ReadString("注册码", "AppId").Trim();
                var ftKey = iniFile.ReadString("注册码", "FtKey").Trim();
                var fdKey = iniFile.ReadString("注册码", "FdKey").Trim();
                var frKey = iniFile.ReadString("注册码", "FrKey").Trim();

                log.InfoFormat("appId {0}", appId);
                log.InfoFormat("ftKey {0}", ftKey);
                log.InfoFormat("fdKey {0}", fdKey);
                log.InfoFormat("frKey {0}", frKey);

                _detection = LocatorFactory.GetDetectionLocator(appId, fdKey) as FaceDetection;
                _recognize = new FaceRecognize(appId, frKey);
                _traking = LocatorFactory.GetTrackingLocator(appId, ftKey) as FaceTracking;
                _processor = new FaceProcessor(_traking, _recognize);
                log.Info("初始化人脸识别动态库成功");
            }
            catch (Exception e)
            {
                log.Error("初始化人脸识别动态库失败",e);
            }
        }

        /**
         * 转换人脸图片为人脸模板
         **/
        private FaceModel ToFaceModel(Bitmap bitmap)
        {
            LocateResult locate;
            var code = _detection.Detect(bitmap, out locate);
            if (code == ErrorCode.Ok && locate.HasFace && locate.FaceCount == 1)
            {
                using (var feature = _recognize.ExtractFeature(locate.OffInput, locate.Faces[0], locate.FacesOrient[0]))
                {
                    return feature.FeatureData;
                }
            }
            locate.Dispose();
            return null;
        }

        public void AddToCompare(Bitmap bitmap)
        {
            log.Debug("添加新的比对模型");
            faceModel = ToFaceModel(bitmap);
        }

        public bool MatchOneToOne(Bitmap image1)
        {
            var result1 = _processor.LocateExtract(image1);
            if(result1 == null || result1.Length <= 0)
            {
                return false;
            }

            var sim = _processor.Match(result1[0].FeatureData, faceModel.Data, true);
            return sim > 0.7;
        }
    }
}
